use std::{collections::BTreeMap, sync::Arc};

use bytes::Bytes;
use tokio::sync::{broadcast, Mutex};

use crate::user::User;

// 群聊信息
#[derive(Debug)]
pub struct Meet {
    //群名称
    pub(crate) name: String,
    //群成员
    pub(crate) users: BTreeMap<String, Arc<Mutex<User>>>,
    //群主
    pub(crate) homeowner: Arc<Mutex<User>>,
    //群号
    pub(crate) meet_no: String,
    //广播
    pub(crate) broadcast: broadcast::Sender<Bytes>,
    //群人员数
    pub(crate) user_num: usize,
    //用于接收服务器发来的消息
    pub(crate) listen: Arc<Mutex<broadcast::Receiver<Bytes>>>,
}

impl Meet {
    pub(crate) async fn new(
        homeowner: Arc<Mutex<User>>,
        m_rx: Arc<Mutex<broadcast::Receiver<Bytes>>>,
    ) -> Arc<Mutex<Self>> {
        let h_clone = homeowner.clone();
        let c_lock = h_clone.lock().await;
        let (b_tx, _) = broadcast::channel(1024);

        let mut meet = Self {
            name: c_lock.cc_no.clone().to_string(),
            users: BTreeMap::new(),
            homeowner: homeowner.clone(),
            meet_no: c_lock.cc_no.clone(),
            broadcast: b_tx,
            user_num: 0,
            listen: m_rx,
        };
        //将房主添加到群聊中
        meet.users.insert(c_lock.cc_no.clone(), homeowner).unwrap();
        meet.user_num += 1;
        drop(c_lock);

        let meet_arc = Arc::new(Mutex::new(meet));
        let meet_clone = meet_arc.clone();
        tokio::spawn(async move {
            meet_clone.lock().await.listen().await;
        });

        meet_arc
    }
    pub(crate) async fn join(&mut self, user: Arc<Mutex<User>>) {
        let u_lock = user.lock().await;
        self.users
            .insert(u_lock.cc_no.clone(), user.clone())
            .unwrap();
        self.user_num += 1;
    }

    pub(crate) async fn listen(&self) {
        let mut m_rx = self.listen.lock().await;
        while let Ok(msg) = m_rx.try_recv() {
            self.broadcast(msg).await;
        }
    }
    pub(crate) async fn broadcast(&self, msg: Bytes) {
        self.broadcast.send(msg).unwrap();
    }
}
